﻿using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using LitJson;

#if UNITY_EDITOR
using UnityEditor;
#endif


public class PUEXMeshRenderVisualData {

	public int subMeshIndex;

}


[AddComponentMenu("PUEX/Render/MeshRender")]
public class PUEXMeshRender : PUEXRender {

	#region - Editable property
	[Header("MeshRender:")]
	public Mesh mesh;
	public bool randomSubMesh;
	public bool lockRotateXAxis;
	public bool lockRotateYAxis;
	public bool lockRotateZAxis;
	#endregion
	
	#region - Lifecycle
	public PUEXMeshRender ()
	{
		randomSubMesh = false;
		lockRotateXAxis = false;
		lockRotateYAxis = false;
		lockRotateZAxis = false;
	}

	public void Awake ()
	{
		switch (blendType) {
		case BlendType.BT_NONE: {
			_material = new Material (Shader.Find ("PUEX/mesh_opaque"));
			_material.mainTexture = texture;
			break;
		}
		case BlendType.BT_NORMAL: {
			_material = new Material (Shader.Find ("PUEX/mesh_trans_alpha"));
			_material.mainTexture = texture;
			break;
		}
		case BlendType.BT_ADD: {
			_material = new Material (Shader.Find ("PUEX/mesh_trans_add"));
			_material.mainTexture = texture;
			break;
		}
		case BlendType.BT_MULTIPLY: {
			_material = new Material (Shader.Find ("PUEX/mesh_trans_multiply"));
			_material.mainTexture = texture;
			break;
		}
		}
	}
	#endregion

	#region - Draw
	protected Matrix4x4 getTransformForRender (PUEXParticle particle) 
	{
		Quaternion orientation = particle.orientation;
		
		if (lockRotateXAxis || lockRotateYAxis || lockRotateZAxis) {
			Vector3 eAngles = orientation.eulerAngles;
			if (lockRotateXAxis)
				eAngles.x = 0;
			if (lockRotateYAxis)
				eAngles.y = 0;
			if (lockRotateZAxis)
				eAngles.z = 0;
			orientation = Quaternion.Euler(eAngles);
		}
		
		return Matrix4x4.TRS (particle.position, orientation, particle.dimensions());
	}
	
//	public override void visit ()
//	{
//		renderMesh.Clear ();
//
//		if (randomSubMesh && mesh.subMeshCount > 1) {
//		} else {
//			Vector3[] vertices = new Vector3[ownerEmitter.aliveParticleCount * mesh.vertices.Length];
//			Vector2[] uvs = new Vector2[ownerEmitter.aliveParticleCount * mesh.uv.Length];
//			Color[] colors = new Color[ownerEmitter.aliveParticleCount * mesh.colors.Length];
//			int[] triangles = new int[ownerEmitter.aliveParticleCount * mesh.triangles.Length];
//
//			int index = 0;
//			int verticesOffset = 0;
//			int uvsOffset = 0;
//			int colorsOffset = 0;
//			int trianglesOffset = 0;
//			foreach (var particle in ownerEmitter.particlePool) {
//				if (particle.alive) {
//					Matrix4x4 transform = getTransformForRender(particle);
//
//					for (int i = 0; i < mesh.vertices.Length; i++) {
//						vertices[verticesOffset + i] = transform.MultiplyPoint(mesh.vertices[i]);
//					}
//
//					for (int i = 0; i < mesh.uv.Length; i++) {
//						uvs[uvsOffset + i] = mesh.uv[i];
//					}
//
//					for (int i = 0; i < mesh.colors.Length; i++) {
//						colors[colorsOffset + i] = particle.color;
//					}
//
//					for (int i = 0; i < mesh.triangles.Length; i++) {
//						triangles[trianglesOffset + i] = verticesOffset + mesh.triangles[i];
//					}
//					
//					index++;
//					verticesOffset += mesh.vertices.Length;
//					uvsOffset += mesh.uv.Length;
//					colorsOffset += mesh.colors.Length;
//					trianglesOffset += mesh.triangles.Length;
//				}
//			}
//			
//			renderMesh.vertices = vertices;
//			renderMesh.uv = uvs;
//			renderMesh.colors = colors;
//			renderMesh.triangles = triangles;
//		}
//	}

	public override void draw ()
	{
		foreach (var particle in ownerEmitter.particlePool) {
			if (particle.alive) {
				Matrix4x4 transform = getTransformForRender (particle);
				if (ownerEmitter.keepLocal) {
					transform = ownerEmitter.ownerParticleSystem.systemToWorldTransform * transform;
				}

				for (int i = 0; i < _material.passCount; i++) {
					_material.color = particle.color;
					_material.mainTextureOffset = particle.uvOffset;
					_material.mainTextureScale = particle.uvScale;
					_material.SetPass (i);
				
					if (randomSubMesh && mesh.subMeshCount > 1) {
						if (particle.visualData == null) {
							var visualData = new PUEXMeshRenderVisualData();
							visualData.subMeshIndex = Random.Range(0, mesh.subMeshCount - 1);
							particle.visualData = visualData;

							Graphics.DrawMeshNow (mesh, transform, visualData.subMeshIndex);
						} else {
							var visualData = particle.visualData as PUEXMeshRenderVisualData;
							Graphics.DrawMeshNow (mesh, transform, visualData.subMeshIndex);
						}
					} else {
						Graphics.DrawMeshNow (mesh, transform);
					}
				}
			}
		}
	}
	#endregion

	#region - Serialization
	public override JsonData save (JsonData emitterData, JsonData systemData)
	{
		JsonData ret = base.save (emitterData, systemData);

		if (guiFX) {
			switch (blendType) {
			case BlendType.BT_NONE: {
				ret ["material"] = "material/puex_ui_mesh_opaque.mat";
				break;
			}
			case BlendType.BT_NORMAL: {
				ret ["material"] = "material/puex_ui_mesh_trans_alpha.mat";
				break;
			}
			case BlendType.BT_ADD: {
				ret ["material"] = "material/puex_ui_mesh_trans_add.mat";
				break;
			}
			case BlendType.BT_MULTIPLY: {
				ret ["material"] = "material/puex_ui_mesh_trans_multiply.mat";
				break;
			}
			}
		} else {
			switch (blendType) {
			case BlendType.BT_NONE: {
				ret ["material"] = "material/puex_mesh_opaque.mat";
				break;
			}
			case BlendType.BT_NORMAL: {
				ret ["material"] = "material/puex_mesh_trans_alpha.mat";
				break;
			}
			case BlendType.BT_ADD: {
				ret ["material"] = "material/puex_mesh_trans_add.mat";
				break;
			}
			case BlendType.BT_MULTIPLY: {
				ret ["material"] = "material/puex_mesh_trans_multiply.mat";
				break;
			}
			}
		}

#if UNITY_EDITOR
		ret ["mesh"] = "mesh/" + Path.GetFileNameWithoutExtension(AssetDatabase.GetAssetPath (mesh)) + ".c3b";
#endif
		ret ["random_sub_mesh"] = randomSubMesh;
		
		ret ["lock_rotate_x_axis"] = lockRotateXAxis;
		ret ["lock_rotate_y_axis"] = lockRotateYAxis;
		ret ["lock_rotate_z_axis"] = lockRotateZAxis;
		
		return ret;
	}
	#endregion

}
